package com.enjoyor.soa.traffic.server.efoms.dubbo.manage;

import com.alibaba.dubbo.config.annotation.Service;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceStatusInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.DeviceWranInfo;
import com.enjoyor.soa.traffic.core.efoms.domain.WranTacticsInfo;
import com.enjoyor.soa.traffic.core.efoms.enums.EnumDicPublic;
import com.enjoyor.soa.traffic.core.efoms.service.IDevStatusInfoService;
import com.enjoyor.soa.traffic.core.efoms.service.IDeviceWranInfoService;
import com.enjoyor.soa.traffic.server.efoms.common.Global;

import org.springframework.beans.factory.annotation.Autowired;

import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
public class ManageDevWranHandleService {

	@Autowired
    private IDevStatusInfoService devStatusInfoService;
	
    @Autowired
    private IDeviceWranInfoService deviceWranInfoService;
    
    @Autowired
    private ManageWranTacticsService manageWranTacticsService;

    //设备类别
  	String categoryCode = EnumDicPublic.DEV_CATEGORY.getKey();
  	String categoryName = EnumDicPublic.DEV_CATEGORY.getValue();
  	//连接正常状态
  	String statusNaomalCode = EnumDicPublic.DEVICE_STATUS_ONLINE.getKey();
  	String statusNaomalName = EnumDicPublic.DEVICE_STATUS_ONLINE.getValue();
  	//连接异常状态
  	String statusFailureCode = EnumDicPublic.DEVICE_STATUS_UNLINE.getKey();
  	String statusFailureName = EnumDicPublic.DEVICE_STATUS_UNLINE.getValue();
  	//设备报修使用状态
  	String repUseingCode = EnumDicPublic.DEV_REP_STATUS_USEING.getKey();
  	String repUseingName = EnumDicPublic.DEV_REP_STATUS_USEING.getValue();
  	//状态异常报警类型
  	String statusWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_STATUS.getKey();
  	String statusWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_STATUS.getValue();
  	//状态异常报警等级
  	String statusWranLevelCode = EnumDicPublic.DEV_WRAN_LEVEL_SERIOUS.getKey();
  	String statusWranLevelName = EnumDicPublic.DEV_WRAN_LEVEL_SERIOUS.getValue();
  	
  	//数据报警类型
  	String noWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_NODATA.getKey();
  	String noWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_NODATA.getValue();
  	String offWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_OFFDATA.getKey();
  	String offWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_OFFDATA.getValue();
  	String delayWranTypeCode = EnumDicPublic.DEV_WRAN_TYPE_DELAYDATA.getKey();
  	String delayWranTypeName = EnumDicPublic.DEV_WRAN_TYPE_DELAYDATA.getValue();
    /**
     * 根据获取的设备连接状态数据与本系统状态表、内存同步
     * @param typeCode 设备类型编号
     * @param typeName 设备类型名称
     * @param devId 设备编号
     * @param devName 设备名称
     * @param linkStatusCode 连接状态编号
     * @param linkStatusName 连接状态名称
     * @param personName 默认操作人信息
     * @return ResultPojo
     */
    public void devStatusHandle(String typeCode, String typeName, String devId, String devName, 
    		String linkStatusCode, String linkStatusName, String personName) {
    	String key = typeCode + "-" + devId;
		DeviceStatusInfo deviceStatusPool = Global.DevStatusPool.get(key);
		//更新设备状态表以及对应内存
		if(null == deviceStatusPool) { 
			DeviceStatusInfo deviceStatusInfo = new DeviceStatusInfo(categoryCode, categoryName, typeCode, 
					typeName, devId, devName, linkStatusCode, linkStatusName);
			devStatusInfoService.insertDevStatusInfoOnly(deviceStatusInfo, personName);
			Global.DevStatusPool.put(key, deviceStatusInfo);
		}else if(!linkStatusCode.equals(deviceStatusPool.getLinkStatusCode())) {
			deviceStatusPool.setLinkStatusCode(linkStatusCode);
			deviceStatusPool.setLinkStatusName(linkStatusName);
			devStatusInfoService.updateDevStatusInfo(deviceStatusPool, personName);
			Global.DevStatusPool.put(key, deviceStatusPool);
		}
    }
    
    /**
     * 根据报警策略生成状态异常报警数据
     * @param typeCode 设备类型编号
     * @param typeName 设备类型名称
     * @param devId 设备编号
     * @param devName 设备名称
     * @param linkStatusCode 设备连接状态编号
     * @param personName 默认操作人信息
     * @return ResultPojo
     */
    public void devStatusWranHandle(String typeCode, String typeName, String devId, String devName, 
    		String linkStatusCode, String personName) {
    	//查询是否存在状态异常报警
		DeviceWranInfo deviceWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(categoryCode, 
				typeCode, devId, statusWranTypeCode, "0");
		if(null == deviceWranInfo) {
			//状态异常则生成报警数据
			if(statusFailureCode.equals(linkStatusCode)) {
				String statusWranContent = "连接状态异常";
				DeviceWranInfo deviceWranInsert = new DeviceWranInfo(categoryCode, categoryName, typeCode, 
						typeName, devId, devName, statusWranTypeCode, statusWranTypeName, statusWranLevelCode, 
						statusWranLevelName, statusWranContent);
				deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
			}
		}else {
			//状态异常更新报警数据，正常则删除实时报警且增加历史数据
			if(statusFailureCode.equals(linkStatusCode)) {
				deviceWranInfoService.updateTimeByWranType(categoryCode, typeCode, devId, statusWranTypeCode, null, personName);
			}else if(statusNaomalCode.equals(linkStatusCode)) {
				String devWranId = deviceWranInfo.getDevWranId();
				deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
				deviceWranInfoService.insertDeviceWranInfoHis(deviceWranInfo, personName);
			}
		}
    }
    /**
     * 根据策略生成数据报警
     * @param typeCode 设备类型编号
     * @param typeName 设备类型名称
     * @param devId 设备编号
     * @param devName 设备名称
     * @param collectTime 采集时间
     * @param receiveTime 接收时间
     * @param writeDbTime 入库时间
     * @param personName 默认操作人信息
     * @return ResultPojo
     */
    public void devDataWranHandle(String typeCode, String typeName, String devId, String devName, 
    		String collectTime, String receiveTime, String writeDbTime,String picUrl,String personName) {
    	String key = typeCode + "-" + devId;
		Boolean isNoWran = false;
		Boolean isOffWran = false;
		Boolean isDelayWran = false;
    	String noWranLevelCode = "";
    	String noWranLevelName = "";
    	String offWranLevelCode = "";
    	String offWranLevelName = "";
    	String delayWranLevelCode = "";
    	String delayWranLevelName = "";

		int noDataTime = 0;
		int offDataTime = 0;
		int delayDataTime = 0;
    	//查询是否存在数据疑似丢失报警策略
    	if(null != receiveTime) {
    		List<WranTacticsInfo> wranTacticsListNo = manageWranTacticsService.selectWranTacticsList(
        			noWranTypeCode, typeCode, null);
        	List<WranTacticsInfo> wranTacticsListOff = manageWranTacticsService.selectWranTacticsList(
        			offWranTypeCode, typeCode, null);
        	if(null != wranTacticsListNo && wranTacticsListNo.size() > 0) {
        		for(WranTacticsInfo wranTacticsInfo : wranTacticsListNo) {
					int minValue = wranTacticsInfo.getMinValue();
					int maxValue = wranTacticsInfo.getMaxValue();
					double intervalTimes = (new Date().getTime() - dateStrToLong(receiveTime))/60000;
					if( intervalTimes >= minValue && intervalTimes <= maxValue ) {
						isNoWran = true;
						noDataTime = (int)intervalTimes;
						noWranLevelCode = wranTacticsInfo.getWranLevelCode();
						noWranLevelName = wranTacticsInfo.getWranLevelName();
						break;
					}
				}
        	}
        	if(null != wranTacticsListOff && wranTacticsListOff.size() > 0) {
        		for(WranTacticsInfo wranTacticsInfo : wranTacticsListOff) {
					int minValue = wranTacticsInfo.getMinValue();
					double intervalTimes = (new Date().getTime() - dateStrToLong(receiveTime))/60000;
					if(intervalTimes >= minValue) {
						isOffWran = true;
						offDataTime = (int)intervalTimes;
						offWranLevelCode = wranTacticsInfo.getWranLevelCode();
						offWranLevelName = wranTacticsInfo.getWranLevelName();
						break;
					}
				}
        	}
        	
        	//判断疑似数据丢失报警
			DeviceWranInfo noWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(categoryCode, 
					typeCode, devId, noWranTypeCode, "0");
			if(null == noWranInfo) {
				//疑似数据丢失 但是未脱机；新增报警数据
				if(isNoWran && !isOffWran) {
					String wranContent = "已有"+noDataTime+"分钟未上传数据";
					DeviceWranInfo deviceWranInsert = new DeviceWranInfo(categoryCode, categoryName, typeCode, 
							typeName, devId, devName, noWranTypeCode, noWranTypeName, noWranLevelCode, 
							noWranLevelName, wranContent);
					deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
				}
			}else {
				//疑似数据丢失 但是未脱机,更新报警数据;其他情况则删除实时报警且增加历史数据
				if(isNoWran && !isOffWran) {
					String wranContent = "已有"+noDataTime+"分钟未上传数据";
					deviceWranInfoService.updateTimeByWranType(categoryCode, typeCode, devId, 
							noWranTypeCode, wranContent, personName);
				}else {
					String devWranId = noWranInfo.getDevWranId();
					deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
					deviceWranInfoService.insertDeviceWranInfoHis(noWranInfo, personName);
				}
			}
        	
			//判断数据脱机报警
			DeviceWranInfo offWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(categoryCode, 
					typeCode, devId, offWranTypeCode, "0");
			if(null == offWranInfo) {
				//数据脱机,新增报警数据
				if(isOffWran) {
					String wranContent = "已有"+offDataTime+"分钟未上传数据";
					DeviceWranInfo deviceWranInsert = new DeviceWranInfo(categoryCode, categoryName, typeCode, 
							typeName, devId, devName, offWranTypeCode, offWranTypeName, offWranLevelCode, 
							offWranLevelName, wranContent);
					deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
				}
			}else {
				//数据脱机；更新报警数据，其他情况则删除实时报警且增加历史数据
				if(isOffWran) {
					String wranContent = "已有"+offDataTime+"分钟未上传数据";
					deviceWranInfoService.updateTimeByWranType(categoryCode, typeCode, devId, 
							offWranTypeCode, wranContent, personName);
				}else {
					String devWranId = offWranInfo.getDevWranId();
					deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
					deviceWranInfoService.insertDeviceWranInfoHis(offWranInfo, personName);
				}
			}
    	}
    	
    	if(null != collectTime && null != writeDbTime) {
    		List<WranTacticsInfo> wranTacticsListDelay = manageWranTacticsService.selectWranTacticsList(
        			delayWranTypeCode, typeCode, null);
        	if(null != wranTacticsListDelay && wranTacticsListDelay.size() > 0) {
        		for(WranTacticsInfo wranTacticsInfo : wranTacticsListDelay) {
					int minValue = wranTacticsInfo.getMinValue();
					double intervalTimes = (dateStrToLong(writeDbTime) - dateStrToLong(collectTime))/60000;
					if(intervalTimes >= minValue) {
						isDelayWran = true;
						delayDataTime = (int)intervalTimes;
						delayWranLevelCode = wranTacticsInfo.getWranLevelCode();
						delayWranLevelName = wranTacticsInfo.getWranLevelName();
						break;
					}
				}
        	}
			//判断是否有数据延迟报警数据
			DeviceWranInfo delayWranInfo = deviceWranInfoService.selectDeviceWranInfoByKey(categoryCode, 
					typeCode, devId, delayWranTypeCode, "0");
			if(null == delayWranInfo) {
				if(isDelayWran) {
					//新增报警数据
					String wranContent = "采集时间与入库时间相差" + delayDataTime + "分钟";
					DeviceWranInfo deviceWranInsert = new DeviceWranInfo(categoryCode, categoryName, typeCode, 
							typeName, devId, devName, delayWranTypeCode, delayWranTypeName, delayWranLevelCode, 
							delayWranLevelName, wranContent);
					deviceWranInfoService.insertDeviceWranInfo(deviceWranInsert, personName);
				}
			}else {
				//更新报警数据，正常则删除实时报警且增加历史数据
				if(isDelayWran) {
					String wranContent = "采集时间与入库时间相差" + delayDataTime + "分钟";
					deviceWranInfoService.updateTimeByWranType(categoryCode, typeCode, devId, 
							delayWranTypeCode, wranContent, personName);
				}else{
					String devWranId = delayWranInfo.getDevWranId();
					deviceWranInfoService.deleteDeviceWranInfo(devWranId, personName);
					deviceWranInfoService.insertDeviceWranInfoHis(delayWranInfo, personName);
				}
			}
    	}
    	
    	DeviceStatusInfo deviceStatusPool = Global.DevStatusPool.get(key);
		Boolean isHaveData = !(isOffWran || isNoWran);
		Boolean isDelayData = isDelayWran;
		Boolean isPhotoSuccess = false;
		//更新设备状态表以及对应内存
		if(picUrl!=null){
			isPhotoSuccess = isConnect(picUrl);
		}
		if(null == deviceStatusPool) { 
			DeviceStatusInfo deviceStatusInfo = new DeviceStatusInfo(categoryCode, categoryName, 
					typeCode, typeName, devId, devName, isHaveData, isDelayData, writeDbTime,isPhotoSuccess);
			devStatusInfoService.insertDevStatusInfoOnly(deviceStatusInfo, personName);
			Global.DevStatusPool.put(key, deviceStatusInfo);
		}else if(isHaveData != deviceStatusPool.getIsHaveData() || isDelayData != deviceStatusPool.getIsDelayData()
				|| writeDbTime != deviceStatusPool.getLastPassTime()||isPhotoSuccess!=deviceStatusPool.getIsPhotoSuccess()) {
			deviceStatusPool.setIsHaveData(isHaveData);
			deviceStatusPool.setIsDelayData(isDelayData);
			deviceStatusPool.setLastPassTime(writeDbTime);
			deviceStatusPool.setIsPhotoSuccess(isPhotoSuccess);
			devStatusInfoService.updateDevStatusInfo(deviceStatusPool, personName);
			Global.DevStatusPool.put(key, deviceStatusPool);
		}
    }
    
    /**
     * 功能：检测当前URL是否可连接或是否有效,
     * 描述：最多连接网络 5 次, 如果 5 次都不成功，视为该地址不可用
     * @param urlStr 指定URL网络地址
     * @return URL
     */
    public static Boolean isConnect(String urlStr) {
		int counts = 0;
		Boolean flag = false;
		if (urlStr == null || urlStr.length() <= 0) {
			return flag;
		}
		while (counts < 5) {
			try {
				URL url = new URL(urlStr);
				HttpURLConnection con = (HttpURLConnection) url.openConnection();
				int state = con.getResponseCode();
				//System.out.println(counts + "= " + state);
				if (state == 200) {
					flag = true;
					break;
				}
				counts++;
			} catch (Exception ex) {
				counts++;
				continue;
			}
		}
		return flag;
	}
    
    /**
	 * 
	 * @param time
	 * @return
	 */
	public long dateStrToLong(String time) {
		SimpleDateFormat date_s2l = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long date_l = 0l;
		try {
			date_l = date_s2l.parse(time).getTime();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		date_s2l = null;
		return date_l;
	}
}
